package org.news.web.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.ReUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.apache.commons.lang3.ObjectUtils;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.dromara.common.redis.utils.RedisUtils;
import org.dromara.system.domain.SysOss;
import org.dromara.system.domain.vo.SysOssVo;
import org.dromara.system.mapper.SysOssMapper;
import org.news.web.constant.UsersConstant;
import org.news.web.domain.Creators;
import org.news.web.domain.bo.UsersQTBo;
import org.news.web.mapper.CreatorsMapper;
import org.news.web.redis.RedisConstant;
import org.springframework.stereotype.Service;
import org.news.web.domain.bo.UsersBo;
import org.news.web.domain.vo.UsersVo;
import org.news.web.domain.Users;
import org.news.web.mapper.UsersMapper;
import org.news.web.service.IUsersService;

import java.time.Duration;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 用户Service业务层处理
 *
 * @author Gu Ci
 * @date 2024-03-26
 */
@RequiredArgsConstructor
@Service
public class UsersServiceImpl implements IUsersService {

    private final SysOssMapper SysOssMapper;

    private final UsersMapper baseMapper;


    private final CreatorsMapper CreatorsMapper;


    private final CreatorsServiceImpl creatorsServiceImpl;


    /**
     * 查询用户
     */
    @Override
    public UsersVo queryById(Long userId){
        UsersVo usersVo = baseMapper.selectVoById(userId);
//        处理ossid
        if(usersVo != null){
            usersVo.setCoverUrl(SysOssMapper.selectById(usersVo.getCoverPhoto()).getUrl());
            usersVo.setPictureUrl(SysOssMapper.selectById(usersVo.getProfilePicture()).getUrl());
        }
        return usersVo;
    }

    /**
     * 查询用户列表
     */
    @Override
    public TableDataInfo<UsersVo> queryPageList(UsersBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<Users> lqw = buildQueryWrapper(bo);
        Page<UsersVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);

        /**
         * 通过图片ossid 来获取图片链接
         */
        if(ObjectUtils.isNotEmpty(result) && !result.getRecords().isEmpty()){

            List<UsersVo> records = result.getRecords();

            Set<String> coverOssIds = records.stream().map((item -> {
                return item.getCoverPhoto();
            })).collect(Collectors.toSet());

            Set<String> pictureOssIds = records.stream().map((item -> {
                return item.getProfilePicture();
            })).collect(Collectors.toSet());


            Set ossIds = new HashSet();
            ossIds.addAll(coverOssIds);
            ossIds.addAll(pictureOssIds);

            List filterIds = ossIds.stream().toList();

            List<SysOss> pts = SysOssMapper.selectList(new QueryWrapper<SysOss>().in("oss_id", filterIds));

            for(int i=0;i<records.size();i++){
                for(int j=0;j< pts.size();j++){
                    if(records.get(i).getProfilePicture().equals(String.valueOf(pts.get(j).getOssId()))){
                        records.get(i).setPictureUrl(pts.get(j).getUrl());
                    }
                    if(records.get(i).getCoverPhoto().equals(String.valueOf(pts.get(j).getOssId()))){
                        records.get(i).setCoverUrl(pts.get(j).getUrl());
                    }
                }
            }
        }
        return TableDataInfo.build(result);
    }

    /**
     * 查询用户列表
     */
    @Override
    public List<UsersVo> queryList(UsersBo bo) {
        LambdaQueryWrapper<Users> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<Users> buildQueryWrapper(UsersBo bo) {
        LambdaQueryWrapper<Users> lqw = Wrappers.lambdaQuery();
        lqw.like(StringUtils.isNotBlank(bo.getUsername()), Users::getUsername, bo.getUsername());
        lqw.eq(StringUtils.isNotBlank(bo.getEmail()), Users::getEmail, bo.getEmail());
        lqw.eq(bo.getRole() != null, Users::getRole, bo.getRole());
        lqw.eq(StringUtils.isNotBlank(bo.getLocation()), Users::getLocation, bo.getLocation());
        lqw.eq(bo.getStatus() != null, Users::getStatus, bo.getStatus());
        return lqw;
    }

    /**
     * 新增用户
     */
    @Override
    public Boolean insertByBo(UsersBo bo) {
        Users add = MapstructUtils.convert(bo, Users.class);
//        validEntityBeforeSave(add);
        /**
         *  设置默认值
         */
        dfInsertUser(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setUserId(add.getUserId());
        }
        return flag;
    }

    /**
     * 设置用户默认值
     * @param add
     */
    private void dfInsertUser(Users add) {
        add.setJoinDate(new Date());
        if(StringUtils.isEmpty(add.getCoverPhoto())){
            add.setCoverPhoto(UsersConstant.DfBgPt());
        }
        if(StringUtils.isEmpty(add.getProfilePicture())){
            add.setProfilePicture(UsersConstant.DfHeadPt());
        }
//        地区
        if(StringUtils.isEmpty(add.getLocation())){
            add.setLocation("未知");
        }
//        活跃状态
        if(add.getStatus() == null){
            add.setStatus(UsersConstant.HY);
        }
//        角色状态
        if(add.getRole() == null){
            add.setRole(UsersConstant.USERS_ROLE);
        }
//
//        密码进行加密
        add.setPassword(SecureUtil.md5(add.getPassword()));


//         创建创作者
//      判断是否是创作者状态
        if(UsersConstant.CREATORS_ROLE == add.getRole()){
//            把用户数据映射到作者表中
            Creators creators = MapstructUtils.convert(add, Creators.class);
            creators.setProfileIcture(add.getProfilePicture());
//            设置作者默认值
            creatorsServiceImpl.DFInsert(creators);
//            插入
            CreatorsMapper.insert(creators);
        }
    }

    /**
     * 修改用户
     */
    @Override
    public Boolean updateByBo(UsersBo bo) {
        Users update = MapstructUtils.convert(bo, Users.class);
//        validEntityBeforeSave(update);
//        todo 修改状态
//        todo 修改角色
//        如果角色设置为停用 那么 作者表中也是停用
        Creators creators = new Creators();
        creators.setStatus(bo.getStatus());
        CreatorsMapper.update(creators,new LambdaQueryWrapper<Creators>().eq(Creators::getUserId,bo.getUserId()));
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(Users entity){
        //TODO 做一些数据校验,如唯一约束
//       判断手机号码 和 邮箱是否满足要求
        boolean isPhone = ReUtil.isMatch("/^[1][3,4,5,6,7,8,9][0-9]{9}$/", entity.getPhone());
        System.out.println(isPhone);
        if(!isPhone){
            throw new ServiceException("手机号不满足要求");
        }
        boolean isEmail = ReUtil.isMatch("/^[A-Za-z\\d]+([-_.][A-Za-z\\d]+)*@([A-Za-z\\d]+[-.])+[A-Za-z\\d]{2,4}$/", entity.getEmail());
        if(!isEmail){
            throw new ServiceException("邮箱不满足要求");
        }
    }

    /**
     * 批量删除用户
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if(isValid){
            //TODO 做一些业务上的校验,判断是否需要校验
        }
//        todo  删除 用户 首先要删除 用户信息  如果是有创作者身份 需要删除相关文章 还有相关文章的评论
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    @Override
    public int rePassWord(UsersBo bo) {
        if(ObjectUtil.isNull(bo) || bo.getUserId() == null  || bo.getPassword() == null){
            return 0;
        }
        Users update = MapstructUtils.convert(bo, Users.class);
        update.setPassword(SecureUtil.md5(update.getPassword()));
        return baseMapper.updateById(update);
    }

    @Override
    public int createCreatorsByUserId(long id) {

//        1.判断用户是否存在
        Users users = baseMapper.selectById(id);
        if(ObjectUtil.isNull(users)){
            throw new ServiceException("用户不存在 创建失败 ！！！");
        }
//        2.判断是否有作者信息
        Creators creators = CreatorsMapper.selectOne(new LambdaQueryWrapper<Creators>().eq(Creators::getUserId, users.getUserId()));
        if(!ObjectUtil.isNull(creators)){
            throw new ServiceException("作者存在 创建失败 ！！！");
        }
//        3.开始创建
        Creators creator = MapstructUtils.convert(users, Creators.class);
        creator.setCreationTime(new Date());
        creator.setProfileIcture(users.getProfilePicture());
        creator.setUpdateTime(new Date());
        creator.setPublicationCount(0l);
        creator.setFollowersCount(0l);

        int insert = CreatorsMapper.insert(creator);

        return insert;
    }

    /**
     * 查询没有被停用的用户
     *
     * @param key
     * @return
     */
    @Override
    public List<UsersVo> queryNoTYList(String key) {
        if(key == null){
            key = "";
        }
        List<UsersVo> users = baseMapper.selectVoList(new LambdaQueryWrapper<Users>().like(Users::getUsername, key).eq(Users::getStatus,UsersConstant.HY));
        return users;
    }

    @Override
    public String login(UsersQTBo bo) {
        // 1.判断是否存在 手机号登录
        Users users = baseMapper.selectOne(new LambdaQueryWrapper<Users>().eq(Users::getPhone, bo.getPhone()));
        if(ObjectUtil.isNull(users)){
            throw new ServiceException("用户名不存在");
        }
        // 2.判断是否停用
        if(users.getStatus()  == null || users.getStatus() == UsersConstant.TY){
            throw new ServiceException("账号停用 请联系管理员！");
        }
        // 3.判断密码是否一致
        if(!SecureUtil.md5(bo.getPassword()).equals(users.getPassword())){
            throw new ServiceException("密码错误");
        }
        // 4.生成一个user:name user 放入到redis中 设置过期时间半小时
        String name = RandomUtil.randomString(10)+UUID.randomUUID().toString().substring(0,6);
        String key = RedisConstant.USER_KEY+":"+name;
//        创建缓存
        RedisUtils.setCacheObject(key,users.getUserId());
        RedisUtils.expire(key, Duration.ofMinutes(30l));
//        修改最近登录时间
        Users users1 = new Users();
        users1.setUserId(users.getUserId());
        users1.setLastLogin(new Date());
        baseMapper.updateById(users1);
        return name;
    }

    /**
     * 注册
     *
     * @param bo
     * @return
     */
    @Override
    public String register(UsersQTBo bo) {
        // 判断用户名
        if(ObjectUtil.isNotNull(bo) && StringUtils.isBlank(bo.getUsername())){
            throw new ServiceException("用户名不存在");
        }
        // 判断电话是否存在
        if(ObjectUtil.isNotNull(bo) && StringUtils.isBlank(bo.getPhone())){
            throw new ServiceException("phone不存在");
        }
        // 判断用户密码是否一致
        if(ObjectUtil.isNotNull(bo) && (StringUtils.isBlank(bo.getPassword()) || StringUtils.isBlank(bo.getRepassword()))){
            throw new ServiceException("密码不能为空");
        }
        // 判断用户密码是否一致
        if(ObjectUtil.isNotNull(bo) && !bo.getPassword().equals(bo.getRepassword())){
            throw new ServiceException("密码不一致");
        }
        //  判断验证码不能为空
        if(ObjectUtil.isNotNull(bo) && StringUtils.isBlank(bo.getCode())){
            throw new ServiceException("验证码不能为空");
        }
//        判断手机号是否已经被注册
        Long aLong = baseMapper.selectCount(new LambdaQueryWrapper<Users>().eq(Users::getPhone, bo.getPhone()));
        if(aLong>0){
            throw new ServiceException("该手机号以被注册");
        }
        //判断验证码
        // code:手机号
        String s = getCode(bo.getPhone());
        System.out.println(s +":"+bo.getCode());
        if(StringUtils.isBlank(s)  || (!s.equals(bo.getCode()))){
            throw new ServiceException("验证码不正确");
        }
        UsersBo convert = MapstructUtils.convert(bo, UsersBo.class);
        Boolean aBoolean = insertByBo(convert);
        if(aBoolean){
            return "注册成功！";
        }else{
            throw new ServiceException("注册失败!");
        }
    }

    /**
     * 获取验证码
     * @param phone
     * @return
     */
    private String getCode(String phone) {
        if(StringUtils.isBlank(phone)){
            throw new ServiceException("手机号码不存在");
        }
        String cacheObject = RedisUtils.getCacheObject(RedisConstant.CODE_KEY+":"+ phone);
//        String aLong = JSONUtil.toJsonPrettyStr(cacheObject);
//        System.out.println(aLong);
        System.out.println(cacheObject);
        return cacheObject;
    }

    /**
     * 发送验证码
     * @param phone
     */
    @Override
    public String sendCode(String phone) {
//        redis code:phone
        if(StringUtils.isBlank(phone)){
            throw new ServiceException("手机号码不存在");
        }
//      发送验证码 可用时间为5分钟
//        key
        String key = RedisConstant.CODE_KEY+":"+phone;
        String code = RandomUtil.randomNumbers(6);
//        生成验证码
        RedisUtils.setCacheObject(key,code);
        System.out.println("验证码信息显示》》 手机号为："+phone+"    它的验证码为:"+code+"   持续时间5分钟");
        RedisUtils.expire(key,Duration.ofMinutes(5l));

        return code;
    }

    @Override
    public UsersVo getUserInfo(String key) {
        Object cache = RedisUtils.getCacheObject(RedisConstant.USER_KEY + ":" + key);
        System.out.println(cache);
        Long userId = Long.valueOf(String.valueOf(cache));
//          返回用户信息
        UsersVo usersVo = baseMapper.selectVoById(userId);
//          设置url头像
        if(usersVo != null && StringUtils.isNotBlank(usersVo.getProfilePicture())){
            SysOssVo sysOssVo = SysOssMapper.selectVoById(usersVo.getProfilePicture());
            usersVo.setPictureUrl(sysOssVo.getUrl());
        }
        return usersVo;
    }
}
